home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Snippets / SuperSplash 1.0d1 / sources / Shell.cp < prev    next >
Text File  |  1995-10-18  |  12KB  |  552 lines

  1. /*
  2. *    Shell.cp
  3. *
  4. *    SuperSplash
  5. *    ^^^^^^^^^^^
  6. *    Main shell for application
  7. *    © Andrew Nemeth (where applicable), Warrimoo Australia 1994, 1995
  8. *    aznemeng@zeta.org.au
  9. *
  10. *    File created:        3 Oct 95.
  11. *    Modified:            3, 18 Oct 95.
  12. */
  13.  
  14. #include    "gConstDefines.h"                                //     Global #defines & const's
  15. #include    "gVariables.h"                                    //     Global variable defn & 'externs'
  16. #include    "stdHighLevelApple.h"                            //    Application High-Level AE
  17.  
  18. #include    "AZN_DBUG.H"                                    //    debugging utilites
  19. #include    "AZN_TSuperSplash.h"                            //    put up & manage Splash screen
  20.  
  21. #include     <AppleEvents.h>                                //    Mac high level AE
  22. #include    <AEObjects.h>                                    //    mac OSL constants
  23. #include    <LowMem.h>
  24. #include    <Gestalt.h>
  25. #include    <Balloons.h>                                    //    Access to System 7 help menu
  26. #include     <limits.h>                                    //    For LONG_MAX
  27.  
  28.  
  29. //    FILE DEFINES…
  30. //
  31.  
  32. //                                                        'stopMask' parameter in '::FlushEvents()'
  33. const short            kshZapEvents = 0;
  34.  
  35.  
  36. //    PROGRAM GLOBALS
  37. //
  38. struct myGlobalStruct     * gptrGlobalsRec = NULL;
  39.  
  40.  
  41. //    FILE GLOBALS
  42. //
  43. static     MenuHandle    ghMenus[ kMenusInBar ];
  44. static     Boolean        gboolUpdateMenus;
  45. static     RgnHandle        ghMouseRgn;
  46.  
  47. //    Globals used to “tune” the performance of MainEventLoop
  48. //    (assume we’ll be starting in the foreground)
  49.  
  50. static    unsigned long    gulgRunQuantum;
  51. static    unsigned long    gulgSleepQuantum;
  52.  
  53.  
  54.  
  55. //     FILE FUNCTIONS…
  56. //
  57. static void     toolBoxInit        ( void );
  58. static void    assignProgGlobals    ( void );
  59. static void    menuBarInit        ( void );
  60. static void    eventLoop            ( void );
  61. static void    doEvent            ( EventRecord * );
  62.  
  63. static void    doMouseDown        ( EventRecord * );
  64. static void     doMenuChoice        ( long );
  65. static void     doAppleChoice        ( short );
  66. static void    doFileChoice        ( short );
  67. static void    doOptionsChoice    ( short );
  68.  
  69. static void    doKeyPress        ( EventRecord * );
  70. static void    maintainMenus        ( Boolean );
  71. static void    quitNow            ( void );
  72.  
  73.  
  74.  
  75. void        main( void )
  76. //
  77. {
  78.     OSErr    myErr;
  79.     long        lgFeature;
  80.  
  81.  
  82.     toolBoxInit();
  83.  
  84.     INIT_DEBUG();
  85. //                                                        MUST be system 7!
  86.     myErr = ::Gestalt( gestaltSystemVersion, &lgFeature );
  87.     if ( myErr == noErr && ( lgFeature < 0x0700 ) ) 
  88.         ExitToShell();
  89. //                                                        need QuickTime for JPEG images
  90.     myErr = ::Gestalt( gestaltQuickTimeVersion, &lgFeature );
  91.     if ( ( myErr == noErr ) && ( lgFeature < 0x0200 ) )
  92.         {
  93.         ::Alert( kresidALRT_QuickTime, NULL );
  94.         }
  95.  
  96.     assignProgGlobals();
  97.  
  98.     menuBarInit();
  99.  
  100.     eventLoop();    
  101. }
  102.  
  103.  
  104.  
  105. void         toolBoxInit( void )
  106. //
  107. //    Initialise toolbox and memory 
  108. //
  109. {
  110.     ::InitGraf( &qd.thePort );
  111.     ::InitFonts( );
  112.     ::FlushEvents( everyEvent, kshZapEvents );
  113.     ::InitWindows( );
  114.     ::TEInit( );
  115.     ::InitDialogs( 0L );
  116.     ::InitCursor( );
  117. //                                                        cut down on heap fragmentation
  118.     ::MaxApplZone( );
  119.     ::MoreMasters( );
  120.     ::MoreMasters( );
  121. //                                                        fire up high leve AE
  122.     highLevelEventInit();
  123. }
  124.  
  125.  
  126.  
  127. void        assignProgGlobals( void )
  128. //
  129. //    A single place to assign all
  130. //    program–wide globals
  131. //
  132. {
  133. //                                                        create global struct on heap
  134.     gptrGlobalsRec = (myGlobalStruct *)::NewPtrClear( sizeof( myGlobalStruct ) );
  135.  
  136.     //    Note on the above
  137.     //    Don't use 'gptrGlobalsRec = new struct myGlobalStruct;' !
  138.     //    Operator new in ANSI library allocates blocks of 
  139.     //    memory in 65532 byte slabs.  As this global will be 
  140.     //    hanging around for the entire program, it is
  141.     //    much more efficient to only allocate a ptr of
  142.     //    size 352 bytes (or so).
  143.     //
  144. //                                                        initialise global values
  145.     if ( gptrGlobalsRec )
  146.         {
  147.         gptrGlobalsRec->boolDone = FALSE;
  148. //                                                        event 'tuning' globals
  149.         gptrGlobalsRec->foregroundRunQuantum = 0L;    
  150.         gptrGlobalsRec->foregroundSleepQuantum = GetCaretTime( );
  151.         gptrGlobalsRec->backgroundRunQuantum = 0L;
  152.         gptrGlobalsRec->backgroundSleepQuantum = LONG_MAX;
  153.         }
  154. }
  155.  
  156.  
  157. void         menuBarInit( void )
  158. //
  159. //    Install about menu and then
  160. //    zap all items in menubar
  161. //
  162. {
  163.     MenuHandle    hMenu = NULL;
  164.     Handle        hMenuBar = NULL;
  165.  
  166.  
  167.     hMenuBar = ::GetNewMBar( kMenuBar_ID );
  168.     ASSERT( hMenuBar != nil );
  169.     
  170.     ::SetMenuBar( hMenuBar );
  171. //                                                        assign Global MenuHandle Array
  172.     for ( short i = kAppleNdx, j = kMApple_ID; i < kMenusInBar ; i++, j++ )
  173.         {
  174.         ghMenus[ i ] = (MenuHandle)::GetMenu( j );
  175.         ASSERT( ghMenus[ i ] != nil );
  176.         }
  177. //                                                        insert 'About Application' into apple Menu
  178.     hMenu = ::GetMHandle( kMApple_ID );
  179.     ASSERT( hMenu != nil );
  180.  
  181.     ::AddResMenu( hMenu, 'DRVR' );
  182.  
  183.     ::DrawMenuBar( );
  184.     gboolUpdateMenus = FALSE;
  185. }
  186.  
  187.  
  188.  
  189. void         eventLoop( void )
  190. //
  191. //    Main event handling loop
  192. //
  193. {
  194.     EventRecord        erRec;
  195.     unsigned long        ulgCheckEvents = 0L;
  196.  
  197.  
  198.     gulgRunQuantum = gptrGlobalsRec->foregroundRunQuantum;
  199.     gulgSleepQuantum = gptrGlobalsRec->foregroundSleepQuantum;
  200.     ghMouseRgn = nil;
  201.     gboolUpdateMenus = TRUE;
  202.  
  203.     gptrGlobalsRec->boolDone = FALSE;
  204.  
  205.     while ( ! gptrGlobalsRec->boolDone )
  206.         {
  207.         if ( gulgRunQuantum == 0  || ( ::TickCount( ) > ulgCheckEvents ) )
  208.             {
  209.             ulgCheckEvents = ::TickCount() + gulgRunQuantum;
  210.             ::WaitNextEvent( everyEvent, &erRec, gulgSleepQuantum, ghMouseRgn );
  211.             doEvent( &erRec );
  212.             }
  213.         }
  214. //                                                        final tidy-up prior to exit
  215.     quitNow();
  216. }
  217.  
  218.  
  219.  
  220.  
  221. void         doEvent( EventRecord *ptrEventRec )
  222. //
  223. //    Events are first dealt with here
  224. //    Note: most of these events are processed
  225. //    in the individual dialogFilter procedures!
  226. //
  227. {
  228.     switch ( ptrEventRec->what )
  229.         {
  230. //                                                        null events
  231.         case nullEvent:
  232.             break;
  233. //                                                        see 'stdHighLevelApple.cp'
  234.         case kHighLevelEvent:
  235.             ::AEProcessAppleEvent( ptrEventRec );
  236.             break;
  237. //                                                        key press
  238.         case autoKey:
  239.         case keyDown:
  240.             doKeyPress( ptrEventRec );
  241.             break;
  242. //                                                        rat press
  243.         case mouseDown:
  244.             doMouseDown( ptrEventRec );
  245.             break;
  246. //                                                        not handled
  247.         case activateEvt:
  248.         case updateEvt:
  249.             break;
  250. //                                                        disc insertions
  251.         case diskEvt:
  252.             if ( ptrEventRec->message >> 16 )
  253.                 {
  254.                 static    Point    where = { 50, 50 };
  255.                 ::DIBadMount( where, ptrEventRec->message );
  256.                 }
  257.             break;
  258. //                                                        multi-finder foreground/ background
  259.         case    osEvt:
  260.             switch ( ( ptrEventRec->message & osEvtMessageMask ) >> 24 )
  261.                 {
  262.                 case    mouseMovedMessage:
  263.                     break;
  264.                     
  265.                 case    suspendResumeMessage:                    
  266.                     if ( ptrEventRec->message & resumeFlag )
  267.                         {
  268.                         ::SetCursor( &qd.arrow );
  269.  
  270.                         gulgRunQuantum = gptrGlobalsRec->foregroundRunQuantum;
  271.                         gulgSleepQuantum = gptrGlobalsRec->foregroundSleepQuantum;
  272.                         }
  273.                     else
  274.                         {
  275.                         gulgRunQuantum = gptrGlobalsRec->backgroundRunQuantum;
  276.                         gulgSleepQuantum = gptrGlobalsRec->backgroundSleepQuantum;
  277.                         }
  278.                     break;
  279.                 }
  280.             break;
  281.         }
  282. //                                                        update menus when there's an interesting event
  283.     if ( ptrEventRec->what != nullEvent && gboolUpdateMenus )
  284.         maintainMenus( TRUE );
  285. }
  286.  
  287.  
  288.  
  289. void         doMouseDown( EventRecord  *ptrEventRec )
  290. //
  291. //    Someone squeezed the rat…
  292. //
  293. {
  294.     WindowPtr        ptrWindow;
  295.     short        thePart;
  296.     long            lgMenuChoice;
  297.     
  298.  
  299.     thePart = ::FindWindow( ptrEventRec->where, &ptrWindow );
  300.     switch( thePart )
  301.         {
  302. //                                                        menu selected
  303.         case inMenuBar:
  304.             lgMenuChoice = ::MenuSelect( ptrEventRec->where );
  305.             doMenuChoice( lgMenuChoice );
  306.             break;
  307. //                                                        window dragged about - not handled
  308.         case inDrag:
  309.         case inContent:
  310.             break;
  311. //                                                        DA's
  312.         case inSysWindow:
  313.             ::SystemClick( ptrEventRec, ptrWindow );
  314.             gboolUpdateMenus = TRUE;
  315.             break;
  316.         }
  317. }
  318.  
  319.  
  320.  
  321. void         doMenuChoice( long lgMenuChoice )
  322. //
  323. //    Menu chosen
  324. //
  325. {
  326.     short        menu;
  327.     short        shMenuItem;
  328.     
  329.  
  330.     if ( lgMenuChoice != 0 )
  331.         {
  332. //                                                        Macros to break 4-byte value into 2 shorts
  333.         menu = HiWord( lgMenuChoice ); 
  334.         shMenuItem = LoWord( lgMenuChoice );
  335.             
  336.         switch( menu )
  337.             {
  338.             case kMApple_ID:
  339.                 doAppleChoice( shMenuItem );
  340.                 break;
  341.  
  342.             case kMFile_ID:
  343.                 doFileChoice( shMenuItem );
  344.                 break;
  345.  
  346.             case kMOptions_ID:
  347.                 doOptionsChoice( shMenuItem );
  348.                 break;
  349. //                                                        system 7 Help menu - not handled
  350.             case kHMHelpMenuID:
  351.                 break;
  352. //                                                        catch-all escape to quit application
  353.             default:
  354.                 quitNow( );
  355.                 break;
  356.             }
  357.         ::HiliteMenu( 0 );
  358.         }
  359. }
  360.  
  361.  
  362.  
  363. void         doAppleChoice( short shMenuItem )
  364. //
  365. //    'About Application' chosen or DA
  366. //
  367. {
  368.     MenuHandle    appleMenu = NULL;
  369.     Str255        accName = { kEmptyString };
  370.     short        accNumber;
  371.     
  372.  
  373.     switch ( shMenuItem )
  374.         {
  375.         case kM_About:
  376. //                                                        knockout highlight on apple menu
  377.             ::FlashMenuBar( kMApple_ID );
  378.             ::NoteAlert( kresidALRT_About, kNilFilterProc );
  379.             gboolUpdateMenus = TRUE;
  380.             break;
  381. //                                                        existing Apple Menus
  382.         default:
  383.             appleMenu = ::GetMHandle( kMApple_ID );
  384.             ::GetItem( appleMenu, shMenuItem, accName );
  385.             accNumber = ::OpenDeskAcc( accName );
  386.             gboolUpdateMenus = TRUE;
  387.             break;
  388.         }
  389. }
  390.  
  391.  
  392.  
  393. void        doFileChoice( short shMenuItem )
  394. //
  395. //    Parse 'File' menu choice
  396. //
  397. {
  398.     switch( shMenuItem )
  399.         {
  400. //                                                        signal ready for quit
  401.         case kM_Quit:
  402.         default:
  403.             gptrGlobalsRec->boolDone = TRUE;
  404.             break;
  405.         }
  406. }
  407.  
  408.  
  409.  
  410. void        doOptionsChoice( short shMenuItem )
  411. //
  412. //    Parse 'Options' menu choice
  413. //
  414. {
  415.     ConstStr63Param    kstr63JPEGName = { "\pIMAGE.jpeg" },
  416.                     kstr36PICTName = { "\pIMAGE.pict" };
  417.     const short        kshPICT_Res_ID = 2000;
  418.  
  419.     TSuperSplash        * ptrobjSplash = NULL;
  420.     Boolean            boolSplashSuccess = FALSE;
  421.     OSErr            myErr = noErr;
  422.  
  423.  
  424.     //    Show-off the three ways of splashing an image
  425.  
  426.     switch( shMenuItem )
  427.         {
  428.         //    Given the name of a JPEG file in the same directory
  429.         //    as the application, use the image in it as that
  430.         //    for the splashscreen
  431.         //
  432.         case kM_Splash_JPEG_file:
  433.             ptrobjSplash = new TSuperSplash( kstr63JPEGName );
  434.             break;
  435.  
  436.         //    Do the same for a PICT file
  437.         //
  438.         case kM_Splash_PICT_file:
  439.             ptrobjSplash = new TSuperSplash( kstr36PICTName );
  440.             break;
  441.  
  442.         //    Splash a PICT resource located in the
  443.         //    application's resource fork
  444.         //
  445.         case kM_Splash_PICT_resource:
  446.             ptrobjSplash = new TSuperSplash( kshPICT_Res_ID );
  447.             break;
  448. //                                                        catch-all in case of stupidity!
  449.         default:
  450.             quitNow();
  451.             break;
  452.         }
  453. //                                                        get image on screen
  454.     boolSplashSuccess = ptrobjSplash->showSplash();
  455. //                                                        stall until mouse click
  456.     if ( boolSplashSuccess )
  457.         {
  458.         ::SetCursor( &qd.arrow );
  459.         while ( ! ::Button() )    
  460.             NULL;
  461.         ::FlushEvents( mDownMask, kshZapEvents );
  462.         }
  463.     else
  464.         ::SysBeep(1);
  465.         //    N.B.  Failure will happen if:
  466.         //    1.    TSuperSplash couldn't find the file in question
  467.         //    2.    Tried to splash a JPEG file & there is no QuickTime installed 
  468.         //    3.    Usual resource or file error (image file corrupted)
  469.  
  470. //                                                        get rid of splash screen
  471.     ptrobjSplash->killSplash();
  472.  
  473.     delete ptrobjSplash;
  474.     gboolUpdateMenus = TRUE;
  475. }
  476.  
  477.  
  478.  
  479. void        doKeyPress( EventRecord *ptrEventRec  )
  480. //
  481. //    Respond to cmd-'' keypresses
  482. //
  483. {
  484.     register char        chCharPressed;
  485.  
  486.  
  487.     chCharPressed = ptrEventRec->message & charCodeMask;
  488.  
  489.     if ( ( ptrEventRec->modifiers & cmdKey ) != 0 )
  490.         {
  491. //                                                        quit now 'cmd-/' key press
  492.         if ( chCharPressed == '/' && ptrEventRec->modifiers & cmdKey )
  493.             quitNow( );
  494.         else
  495.             doMenuChoice( MenuKey( chCharPressed ) );
  496.         }
  497. }
  498.  
  499.  
  500.  
  501. void        maintainMenus( Boolean boolEnableAll )
  502. //
  503. //    Make sure menus reflect 
  504. //    current state of application
  505. //    If 'boolEnableAll' is FALSE, then menubar
  506. //    is deactivated
  507. //
  508. {
  509.     const short    kshDoForAll = 0;
  510.     short    i;
  511.  
  512.  
  513.     //    Enable/ disable all menu bar headings
  514.     //
  515.     for ( i = kAppleNdx; i < kMenusInBar ; i++ )
  516.         {
  517.         if ( boolEnableAll )
  518.             ::EnableItem( ghMenus[ i ], kshDoForAll );
  519.         else
  520.             ::DisableItem( ghMenus[ i ], kshDoForAll );
  521.         }
  522.  
  523. //                                                        enable/ disable individual items
  524.     if ( boolEnableAll )
  525.         {
  526. //                                                        always activate
  527.         ::EnableItem( ghMenus[ kFileNdx ], kM_Quit );
  528.  
  529.         ::EnableItem( ghMenus[ kOptionsNdx ], kM_Splash_JPEG_file );
  530.         ::EnableItem( ghMenus[ kOptionsNdx ], kM_Splash_PICT_file );
  531.         ::EnableItem( ghMenus[ kOptionsNdx ], kM_Splash_PICT_resource );
  532. //                                                        wait for update!
  533.         ::InvalMenuBar( );
  534.         }
  535. //                                                        deactivate mbar NOW!
  536.     else
  537.         ::DrawMenuBar( );
  538.  
  539.     gboolUpdateMenus = FALSE;
  540. }
  541.  
  542.  
  543.  
  544. void        quitNow( void )
  545. //
  546. //    When the cmd—'/' is pressed,
  547. //    things to do before exit
  548. //
  549. {
  550.     gptrGlobalsRec->boolDone = TRUE;
  551. }
  552.